package modelController.applicationController;

import entities.Edgeamongknowledge;
import entities.Knowledge;
import entities.Subject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ejb.EJB;
import javax.enterprise.context.ApplicationScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.inject.Inject;
import javax.inject.Named;
import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.DirectedMultigraph;
import sessionBeans.SubjectFacadeLocal;

@Named("subjectControllerA")
@ApplicationScoped
public class SubjectController extends ApplicationCommonController {

    @EJB
    private sessionBeans.SubjectFacadeLocal ejbFacadelocal;
    @Inject
    private modelController.applicationController.KnowledgeController applicationKnowledgeController;
    @Inject
    private modelController.applicationController.EdgeamongknowledgeController applicationEdgeamongknowledgeController;
    @Inject
    private modelController.applicationController.PredicateController applicationPredicateController;

    private SubjectFacadeLocal getFacade() {
        return ejbFacadelocal;
    }

    public Subject getSubject(java.lang.Integer id) {
        setDataChanged(false);
        return getFacade().find(id);
    }

    public void create(Subject subject) {
        getFacade().create(subject);
        setDataChanged(true);
    }

    public void remove(Subject subject) {
        getFacade().remove(subject);
        setDataChanged(true);
    }

    public void edit(Subject subject) {
        getFacade().edit(subject);
        setDataChanged(true);
    }

    public List<Subject> getQueryResultList(String sql) {
        setDataChanged(false);
        return getFacade().getQueryResultList(sql);
    }

    @FacesConverter(forClass = Subject.class)
    public static class SubjectControllerConverter implements Converter {

        @Override
        public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
            if (value == null || value.length() == 0||value.equals("null")) {
                return null;
            }
            SubjectController controller = (SubjectController) facesContext.getApplication().getELResolver().
                    getValue(facesContext.getELContext(), null, "subjectControllerA");
            return controller.getSubject(Integer.valueOf(value));
        }

        @Override
        public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
            if (object == null) {
                return null;
            }
            if (object instanceof Subject) {
                Subject o = (Subject) object;
                return String.valueOf(o.getId());
            } else {
                throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + Subject.class.getName());
            }
        }

    }

    public String getKnowlegeIdsString(Subject subject) {
        List<Integer> ids = applicationKnowledgeController.getKnowledgeId4Subject(subject);
//        String result = "";
//        if (null != subject && null != subject.getId()) {
//            List<Knowledge> knowledgeSet = applicationKnowledgeController.getKnowledgeList4Subject(subject);
//            for (Knowledge knowledge : knowledgeSet) {
//                result += "," + knowledge.getId();
//            }
//        }
//        if (result.trim().length() > 0) {
//            result = result.substring(1);
//        }
        if (ids.size() > 0) {
            return ids.toString().substring(1, ids.toString().length() - 1);
        } else {
            return "";
        }
    }

    public int count() {
        setDataChanged(false);
        return getFacade().count();
    }

    public void executUpdate(String updateString) {
        setDataChanged(true);
        getFacade().executUpdate(updateString);
    }

    public List<Subject> findRange(int[] range) {
        setDataChanged(false);
        return getFacade().findRange(range);
    }

    public Subject find(Integer id) {
        setDataChanged(false);
        return getFacade().find(id);
    }

    public Set getAllSet() {
        return new HashSet(getFacade().findAll());
    }

    public List<Subject> getAllList() {
        setDataChanged(false);
        return getFacade().findAll();
    }

    public Subject findByName(String name) {
        setDataChanged(false);
        return getFacade().findByName(name);
    }

    HashMap<Integer, Subject> subjectMap;

    public HashMap<Integer, Subject> getSubjectMap() {
        if (subjectMap == null || subjectMap.isEmpty()) {
            List<Subject> all = getFacade().findAll();
            for (Subject subject : all) {
                subjectMap.put(subject.getId(), subject);
            }
        }
        return subjectMap;
    }

    private HashMap<Subject, Graph> existedGraph = new HashMap<>();

    public Graph<Knowledge, DefaultEdge> getGraphofKnowledge(Subject subject) {
        if (existedGraph.get(subject) == null) {
            Graph<Knowledge, DefaultEdge> directedGraph = new DirectedMultigraph<>(DefaultEdge.class);
            subject.getKnowledgeSet().forEach((knowledge) -> {
                directedGraph.addVertex(knowledge);
            });
            HashSet<Edgeamongknowledge> temSet1 = new HashSet<>();
            subject.getKnowledgeSet().stream().map((knowledge) -> {
                Set<Edgeamongknowledge> temSet = knowledge.getPredcessorKnowledgeSet();
                for (Edgeamongknowledge edge : temSet) {
                    if (!temSet1.contains(edge)) {
                        directedGraph.addEdge(edge.getPredecessornode(), edge.getSuccessornode());
                        temSet1.add(edge);
                    }
                }
                temSet = knowledge.getSuccessorknowledgeSet();
                return temSet;
            }).forEachOrdered((temSet) -> {
                for (Edgeamongknowledge edge : temSet) {
                    if (!temSet1.contains(edge)) {
                        directedGraph.addEdge(edge.getPredecessornode(), edge.getSuccessornode());
                    }
                }
            });
            existedGraph.put(subject, directedGraph);
        }
        return existedGraph.get(subject);
    }

    public void repaireKnowledgeRelation() {
        List<Subject> allSubject = getAllList();
        for (Subject subject : allSubject) {
            if (subject.getStartKnowledge() == null) {
                Knowledge knowledge = null;
                List<Knowledge> candiKnowledge = applicationKnowledgeController.getQueryResultList("select * from knowledge where subject_id=" + subject.getId() + " and ( name like '%start'or name like '%Start')");
                if (candiKnowledge.size() > 0) {
                    knowledge = candiKnowledge.get(0);
                } else {
                    knowledge = applicationKnowledgeController.createStart(subject);
                }
                subject.setStartKnowledge(knowledge);
                edit(subject);
            }
        }
        applicationKnowledgeController.repaireKnwoledge();
        System.out.println("完成修复");
    }
    HashMap<Subject, List<Knowledge>> subjectSortedKnowledge;

    public List<Knowledge> getSortedKnowledges(Subject subject) {
        if(subjectSortedKnowledge.get(subject)==null){
            applicationKnowledgeController.getSortedKnowledges(subject);
        }
        return subjectSortedKnowledge.get(subject);
    }

}
